﻿namespace MyWebLog.Tests.Logic.Models.Security
{
    using DatabaseAbstraction.Utils.UnitTest;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using MyWebLog.Logic.Models.Constants;
    using MyWebLog.Logic.Models.Security;
    using System;
    using System.Data;

    /// <summary>
    /// Unit Tests for the Blog User class
    /// </summary>
    [TestClass]
    public class BlogUserTest
    {
        /// <summary>
        /// Test the empty constructor
        /// </summary>
        [TestMethod]
        public void EmptyConstructor()
        {
            var user = new BlogUser();
            Assert.IsNotNull(user, "The user should not be null");
        }

        /// <summary>
        /// Test the data constructor
        /// </summary>
        [TestMethod]
        public void DataConstructor()
        {
            using (var reader = GetData())
            {
                // Check a row will all data filled
                var user = new BlogUser(reader);

                Assert.IsNotNull(user, "The user should not be null");
                Assert.AreEqual(47, user.ID, "ID not filled correctly");
                Assert.AreEqual(UserStatus.Pending, user.Status, "Status ID not filled correctly");
                Assert.AreEqual("bill@test.com", user.EmailAddress, "E-mail Address not filled correctly");
                Assert.AreEqual("Bill", user.FirstName, "First Name not filled correctly");
                Assert.AreEqual("Tester", user.LastName, "Last Name not filled correctly");
                Assert.AreEqual("Testy", user.DisplayName, "Display Name not filled correctly");
                Assert.AreEqual(new DateTime(2010, 7, 14), user.CreatedDate, "Created Date not filled correctly");
                Assert.AreEqual(new DateTime(2011, 3, 9), user.LastSeenDate, "Last Seen Date not filled correctly");
                Assert.AreEqual("ABC123", user.VerificationKey, "Verification Key not filled correctly");

                // Ensure nullable values are handled properly
                reader.Read();
                user = new BlogUser(reader);

                Assert.IsNotNull(user);
                Assert.IsNull(user.LastSeenDate, "Last Seen Date should have been null");
                Assert.IsNull(user.VerificationKey, "Verification Key should have been null");
            }
        }

        /// <summary>
        /// Test the data parameters
        /// </summary>
        [TestMethod]
        public void Parameters()
        {
            using (var reader = GetData())
            {
                var user = new BlogUser(reader);
                Assert.IsNotNull(user);

                var parameters = user.Parameters();
                Assert.IsTrue(parameters.ContainsKey("blog_user_id"),
                    "Blog User ID key not found in parameter dictionary");
                Assert.IsTrue(parameters.ContainsKey("status_id"), "Status ID key not found in parameter dictionary");
                Assert.IsTrue(parameters.ContainsKey("email_address"),
                    "E-mail Address key not found in parameter dictionary");
                Assert.IsTrue(parameters.ContainsKey("password_hash"),
                    "Password Hash key not found in parameter dictionary");
                Assert.IsTrue(parameters.ContainsKey("first_name"), "First Name key not found in parameter dictionary");
                Assert.IsTrue(parameters.ContainsKey("last_name"), "Last Name key not found in parameter dictionary");
                Assert.IsTrue(parameters.ContainsKey("display_name"),
                    "Display Name key not found in parameter dictionary");
                Assert.IsTrue(parameters.ContainsKey("created_date"),
                    "Created Date key not found in parameter dictionary");
                Assert.IsTrue(parameters.ContainsKey("last_seen_date"),
                    "Last Seen Date key not found in parameter dictionary");
                Assert.IsTrue(parameters.ContainsKey("verification_key"),
                    "Verification Key key not found in parameter dictionary");

                Assert.AreEqual(47, parameters["blog_user_id"], "User ID incorrect");
                Assert.AreEqual((int)UserStatus.Pending, parameters["status_id"], "Status ID incorrect");
                Assert.AreEqual("bill@test.com", parameters["email_address"], "E-mail Address incorrect");
                Assert.IsNull(parameters["password_hash"], "Password Hash should have been null");
                Assert.AreEqual("Bill", parameters["first_name"], "First Name incorrect");
                Assert.AreEqual("Tester", parameters["last_name"], "Last Name incorrect");
                Assert.AreEqual("Testy", parameters["display_name"], "Display Name incorrect");
                Assert.AreEqual(new DateTime(2010, 7, 14), parameters["created_date"], "Created Date incorrect");
                Assert.AreEqual(new DateTime(2011, 3, 9), parameters["last_seen_date"], "Last Seen Date incorrect");
                Assert.AreEqual("ABC123", parameters["verification_key"], "Verification Key incorrect");

                reader.Read();

                user = new BlogUser(reader);
                user.PasswordHash = "PwH";

                parameters = user.Parameters();
                Assert.IsNotNull(parameters);

                Assert.AreEqual("PwH", parameters["password_hash"], "Password Hash incorrect");
                Assert.IsNull(parameters["last_seen_date"], "Last Seen Date should have been null");
                Assert.IsNull(parameters["verification_key"], "Verification Key should have been null");
            }
        }

        /// <summary>
        /// Get a reader with test data, pointing to a row of test data
        /// </summary>
        /// <returns>
        /// A ready-to-use data reader
        /// </returns>
        private IDataReader GetData()
        {
            var results = new StubResultSet("blog_user_id", "status_id", "email_address", "first_name", "last_name",
                "display_name", "created_date", "last_seen_date", "verification_key");

            results.AddRow(47, (int)UserStatus.Pending, "bill@test.com", "Bill", "Tester", "Testy",
                new DateTime(2010, 7, 14), new DateTime?(new DateTime(2011, 3, 9)), "ABC123");
            results.AddRow(28, (int)UserStatus.Confirmed, "brad@test.com", "Brad", "Tested", "Bradley",
                new DateTime(2010, 11, 24), DBNull.Value, DBNull.Value);

            var reader = new StubDataReader(results);
            reader.Read();

            return reader;
        }
    }
}